#include "uart.h"

#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <stdio.h>

#include "hi_common.h"

#define UART_FRAME_BUF_SIZE 128

HI_S32 UartInit(HI_S32 UartDev)
{
    HI_S32 s32Ret = 0;

    HI_CHAR acUartDev[20] = {0};
    sprintf_s(acUartDev, sizeof(acUartDev), "/dev/ttyAMA%d", UartDev);
    HI_S32 UartFd = open(acUartDev, O_RDWR | O_NOCTTY | O_NDELAY);
    if (UartFd < 0)
    {
        printf("[FAIL] open \"%s\"\n", acUartDev);
        return HI_FAILURE;
    }

    struct termios UartIO = {0};
    s32Ret = tcgetattr(UartFd, &UartIO);
    if (HI_SUCCESS != s32Ret)
    {
        printf("[FAIL] tcgetattr: %x\n", s32Ret);
        close(UartFd);
        return HI_FAILURE;
    }

    UartIO.c_cflag |= CLOCAL | CREAD;
    UartIO.c_cflag &= ~CSIZE;
    UartIO.c_cflag |= CS8;
    UartIO.c_cflag &= ~PARENB;
    UartIO.c_cflag &= ~CSTOPB;

    cfsetispeed(&UartIO, B115200);
    cfsetospeed(&UartIO, B115200);

    // UartIo.c_iflag &= ~(INLCR | IGNCR | IGNCR);

    UartIO.c_oflag &= ~OPOST;
    
    UartIO.c_cc[VTIME] = 0;
    UartIO.c_cc[VMIN] = 0;

    tcflush(UartFd, TCIFLUSH);

    s32Ret = tcsetattr(UartFd, TCSANOW, &UartIO);
    if (HI_SUCCESS != s32Ret)
    {
        printf("[FAIL] tcsetattr: %x\n", s32Ret);
        close(UartFd);
        return HI_FAILURE;
    }

    close(UartFd);
    return HI_SUCCESS;
}

HI_S32 UartSend(HI_S32 UartDev, const HI_U8 *pu8DataBuf, HI_U8 u8DataLen, HI_BOOL bVerbose)
{
    HI_S32 s32Ret = 0;

    HI_CHAR acUartDev[20] = {0};
    sprintf_s(acUartDev, sizeof(acUartDev), "/dev/ttyAMA%d", UartDev);
    HI_U8 UartFd = open(acUartDev, O_RDWR | O_NOCTTY | O_NDELAY);
    if (UartFd < 0)
    {
        printf("[FAIL] open \"%s\"\n", acUartDev);
        return HI_FAILURE;
    }

    HI_U8 au8SendFrameBuf[UART_FRAME_BUF_SIZE] = {0};
    HI_U8 u8PackageLen = sizeof(u8DataLen) + u8DataLen;
    if (u8PackageLen > UART_FRAME_BUF_SIZE)
    {
        printf("[FAIL] uart package len is exceedig UART_FRAME_BUF_SIZE\n");
        close(UartFd);
        return HI_FAILURE;
    }
    else
    {
        au8SendFrameBuf[0] = u8DataLen;
    }

    memcpy_s(au8SendFrameBuf + 1, u8DataLen, pu8DataBuf, u8DataLen);

    tcflush(UartFd, TCIFLUSH);

    HI_U8 u8SendLen = u8PackageLen;
    HI_U8 u8SendCnt = 0;
    while (u8SendLen > 0)
    {
        HI_S32 s32WriteCnt = write(UartFd, au8SendFrameBuf + u8SendCnt, u8SendLen);
        if (s32WriteCnt < 1)
        {
            printf("[FAIL] write data below 1 byte: %d\n", s32WriteCnt);
            break;
        }
        u8SendCnt += s32WriteCnt;
        u8SendLen -= s32WriteCnt;
    }

    if (u8SendCnt != u8PackageLen)
    {
        printf("[FAIL] UartSend failed!");
        close(UartFd);
        return HI_FAILURE;
    }

    if (bVerbose)
    {
        for (HI_S32 i = 0; i < u8PackageLen; i++)
        {
            printf("[INFO] Send data[%d] = %x\n", i, au8SendFrameBuf[i]);
        }
    }

    close(UartFd);
    return HI_SUCCESS;
}